package cn.italkcloud.cph.utils;

import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 临时缓存工具，只内存中，数据重启后丢失
 * 可以调整这里的函数切换为Redis等缓存中间间
 *
 * @author dominate
 * @since 2025/3/19
 **/
public class CacheUtil {

    private static final Map<String, Long> KEY_OUT_TIME = new LinkedHashMap<>();

    private static final Map<String, Object> CACHE = new HashMap<>();
    private static final long RUN_SYNC_MINUTE = 30;
    private static boolean START_SYNC = false;

    static {
        run();
    }

    public static void run() {
        if (START_SYNC) {
            return;
        }
        START_SYNC = true;
        ScheduledThreadPoolExecutor poolExecutor = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors());
        poolExecutor.scheduleAtFixedRate(() -> {
            long now = System.currentTimeMillis();
            Set<String> removeKeys = new HashSet<>();
            for (Map.Entry<String, Long> cacheKeyEntry : KEY_OUT_TIME.entrySet()) {
                if (cacheKeyEntry.getValue() < now) {
                    removeKeys.add(cacheKeyEntry.getKey());
                }
            }
            for (String removeKey : removeKeys) {
                remove(removeKey);
            }
        }, 0, RUN_SYNC_MINUTE, TimeUnit.MINUTES);

    }

    public static boolean hasKey(String key) {
        return KEY_OUT_TIME.containsKey(key);
    }

    public synchronized static void set(String key, Object data) {
        set(key, data, 0);
    }

    public synchronized static void set(String key, Object data, int timeoutSecond) {
        if (timeoutSecond != 0) {
            KEY_OUT_TIME.put(key, System.currentTimeMillis() + timeoutSecond * 1000L);
        }
        CACHE.put(key, data);
    }

    public synchronized static <T> List<T> getList(String key, Class<T> tClass) {
        Object object = CACHE.get(key);
        if (Objects.nonNull(object)) {
            return BaseUtil.obj2List(object, tClass);
        }
        return null;
    }

    public synchronized static <T> T get(String key, Class<T> tClass) {
        Object object = CACHE.get(key);
        if (Objects.nonNull(object)) {
            return tClass.cast(object);
        }
        return null;
    }

    public synchronized static void remove(String key) {
        if (KEY_OUT_TIME.containsKey(key)) {
            KEY_OUT_TIME.remove(key);
            return;
        }
        CACHE.remove(key);
    }

}
